package main

import (
	"fmt"
	"reflect"
)

func main() {
	first()
	second()
	third()
}
func first() {
	// 反射第一定律：反射可以将“接口类型变量”转换为“反射类型对象”
	var x interface{} = 42
	t := reflect.TypeOf(x)  
	v := reflect.ValueOf(x)
	fmt.Println("Type :", t)       
	fmt.Println("Value:", v)       
	fmt.Println("Kind :", v.Kind())
}
func second() {
	// 反射第二定律：反射可以将“反射类型对象”转换为“接口类型变量”

	// 1. 先拿到反射对象（第一定律）
	v := reflect.ValueOf(42) 
	// 2. 第二定律：反射对象 → 接口变量
	i := v.Interface() 
	// 3. 再类型断言回到具体值
	n := i.(int)
	fmt.Printf("原始值=%d  类型=%T\n", n, n)
}
func third() {
	// 反射第三定律：如果要修改“反射类型对象”其值必须是“可写的”
	// 1. 普通值 —— 不可写（传值）
	// Go 的函数参数永远是“值传递”，reflect.ValueOf(a) 得到的是原值的一份只读副本，改副本影响不到原变量，所以 Go 干脆禁止你写，防止误会。
	a := "hello"
	v1 := reflect.ValueOf(a)
	fmt.Println("v1.CanSet() =", v1.CanSet()) // false
	// v1.SetString("world") // panic: unaddressable

	// 2. 指针解引用 —— 可写（传指针再 Elem）
	v2 := reflect.ValueOf(&a).Elem()
	fmt.Println("v2.CanSet() =", v2.CanSet()) // true
	v2.SetString("world")
	fmt.Println("a =", a) // world
}
